# Учебный проект: Сбор проекта 

Это финальная задача по учебному проекту. К этому моменту вы уже должны были создать все необходимые компоненты, а здесь мы объединим их воедино. 

Готовый проект можно найти по ссылке - <https://course-jsbasic.javascript.ru>.

Создайте класс `Main`, который объединяет все компоненты проекта и отрисовывает их на странице. 

Как вы понимаете, компоненты должны быть размещены на определенных местах на странице. Мы заранее подготовили базовую верстку и специальные элементы, в которые вы будете вставлять компоненты. 

Всю верстку и пример использования класса `Main` можно найти в файле `index.html`.

А на картинке ниже показано, как мы будем размещать компоненты на странице:

<img width="100%" alt="Схема размещения компонентов на странице" src="https://i.imgur.com/Z8p4Ink.png">

## Метод async render()

Реализуйте метод `async render()`, который показывает все компоненты магазина на странице и возвращает промис. 

Этот метод возвращает промис, т.к. товары для отрисовки вы будете получать с сервера.

Ниже приведены требования к реализации метода.

### Создание базовых компонент

Эти компоненты мы можем показать на странице сразу после вызова метода.

1. Создайте экземпляр компонента `Carousel`, передав ему массив слайдов `slides`, и вставьте его корневой элемент внутрь элемента с атрибутом `data-carousel-holder`, который уже находится на странице.

2. Создайте экземпляр компонента `RibbonMenu`, передав ему массив категорий `categories`, и вставьте его корневой элемент внутрь элемента с атрибутом `data-ribbon-holder`, который уже находится на странице.

3. Создайте экземпляр компонента `StepSlider` для 5-и шагов с начальным значением - 3 и вставьте его корневой элемент внутрь элемента с атрибутом `data-slider-holder`, который уже находится на странице.

4. Создайте экземпляр компонента `CartIcon` и вставьте его корневой элемент внутрь элемента с атрибутом `data-cart-icon-holder`, который уже находится на странице.

5. Создайте экземпляр компонента `Cart` передав ему как аргумент созданный ранее экземпляр компонента `CartIcon`.

### Показ списка товаров

Список товаров для отображения хранится на сервере, поэтому, чтобы их отобразить, сначала нужно сделать запрос с помощью `fetch`.

1. Сделайте запрос за товарами по адресу `products.json`. Сервер отдает данные в формате `JSON`, поэтому не забудьте преобразовать результат после получения.

2. После получения массива товаров, создайте экземпляр компонента `ProductsGrid`, передав ему массив товаров с сервера, и вставьте его корневой элемент внутрь элемента с атрибутом `data-products-grid-holder`, который уже находится на странице. 

Также нужно не забыть сделать `await` получения товаров, ведь метод `render` возвращает промис. 

Обращаем ваше внимание, что в этом случае содержимое элемента, в который мы вставляем список товаров, нужно полностью очистить. До получения товаров, мы отображаем внутри него "заглушки" (смотрите файл `index.html`).

### Фильтрация товаров после получения с сервера

После показа товаров, отфильтруйте их по текущим значениям фильтров.

Как вы помните, в нашем проекте предусмотрена фильтрация товаров. И вы уже реализовали слайдер для фильтрации по остроте. 

Помимо этого мы добавили в верстку два дополнительных чекбокса, которые призваны фильтровать товары по критериям: `с орехами/без орехов` и `вегетарианские/не вегетарианские`. У этих чекбоксов добалены `id` со значениями `nuts-checkbox` и `vegeterian-checkbox` соответственно.

В дальнейшем мы будем слушать событие изменения значения и фильтровать товары, но для начала нам нужно обновить список товаров по текущим значениям, вызвав метод `updateFilter`:

```js
//  this.productsGrid -  экземпляр компонента ProductsGrid
//  this.stepSlider -  экземпляр компонента StepSlider
//  this.ribbonMenu -  экземпляр компонента RibbonMenu

this.productsGrid.updateFilter({
  noNuts: document.getElementById('nuts-checkbox').checked,
  vegeterianOnly: document.getElementById('vegeterian-checkbox').checked,
  maxSpiciness: this.stepSlider.value,
  category: this.ribbonMenu.value
});
```

Как вы видите значение категории и максимальной остроты для фильтрации мы берем из экземпляров компонент `StepSlider` и `RibbonMenu` соответственно.

### Связь компонентов через события

Как вы помните, связь между компонентами в нашем проекте происходит через пользовательские события, такие как: `'product-add'`, `'slider-change'`, `'ribbon-select'`.

Добавьте обработчики на пользовательские события и изменения чекбоксов для фильтрации. 

**Пользовательские события:**

1. Если на элементе `body` происходит событие `'product-add'`, то нужно по `productId` из объекта события найти нужный товар в массиве товаров и добавить его в корзину, вызвав метод `addProduct` на экземпляре компонента `Cart`.

2. Если на корневом элементе экземпляра компонента `StepSlider` происходит событие `'slider-change'`, то нужно отфильтровать товары по новому значению остроты, вызвав метод `updateFilter` на экземпляре компонента `ProductsGrid`. Значение остроты, как вы понимаете, мы берем из объекта события.

```js
//  this.productsGrid -  экземпляр компонента ProductsGrid

this.productsGrid.updateFilter({
  maxSpiciness: value // значение остроты из события 'slider-change'
});
```

3. Если на корневом элементе экземпляра компонента `RibbonMenu` происходит событие `'ribbon-select'`, то нужно отфильтровать товары по новому значению категории, вызвав метод `updateFilter` на экземпляре компонента `ProductsGrid`. Новую категорию, как вы понимаете, мы берем из объекта события.

```js
//  this.productsGrid -  экземпляр компонента ProductsGrid

this.productsGrid.updateFilter({
  category: categoryId // категория из события 'ribbon-select'
});
```

Отслеживать события `'slider-change'` и `'ribbon-select'` можно также и на элементе `body`.

**Фильтрация по изменению чекбокосов:**

Для отслеживания изменений на чекбоксах `noNuts` и `vegeterianOnly` мы используем событие `change`. Подробнее про него можно прочитать в статье - [События: change, input, cut, copy, paste](https://learn.javascript.ru/events-change-input).

1. Если событие `change` происходит на чекбоксе с `id` - `nuts-checkbox`, то нужно отфильтровать товары по критерию `с орехами/без орехов`:

```js
//  this.productsGrid -  экземпляр компонента ProductsGrid

this.productsGrid.updateFilter({
  noNuts: checked // новое значение чекбокса
});
```

2. Если событие `change` происходит на чекбоксе с `id` - `vegeterian-checkbox`, то нужно отфильтровать товары по критерию `вегетарианские/не вегетарианские`:

```js
//  this.productsGrid -  экземпляр компонента ProductsGrid

this.productsGrid.updateFilter({
  vegeterianOnly: checked // новое значение чекбокса
});
```

На этом все, ваш проект готов ;)
